import { Callout, Card, Cards, Steps, Tabs } from "nextra/components";
import UniversalTabs from "@/components/UniversalTabs";

# Webhooks

<Callout type="info" emoji="🪓">
  This feature is currently in development and might change. Reach out for
  feedback or if you encounter any problems registering any external webhooks.
</Callout>

Webhooks allow external systems to trigger Hatchet workflows by sending HTTP requests to dedicated endpoints. This enables real-time integration with third-party services like GitHub, Stripe, Slack, or any system that can send webhook events.

## Creating a webhook

To create a webhook, you'll need to fill out some fields that tell Hatchet how to determine which workflows to trigger from your webhook, and how to validate it when it arrives from the sender. In particular, you'll need to provide the following fields:

#### Name

The **Webhook Name** is tenant-unique (meaning a single tenant can only use each name once), and is used to create the URL for where the incoming webhook request should be sent. For instance, if your tenant id was `d60181b7-da6c-4d4c-92ec-8aa0fc74b3e5` and your webhook name was `my-webhook`, then the URL might look like `https://cloud.onhatchet.run/api/v1/stable/tenants/d60181b7-da6c-4d4c-92ec-8aa0fc74b3e5/webhooks/my-webhook`. Note that you can copy this URL in the dashboard.

#### Source

The **Source** indicates the source of the webhook, which can be a pre-provided one for easy setup like Stripe or Github, or a "generic" one, which lets you configure all of the necessary fields for your webhook integration based on what the webhook sender provides.

#### Event Key Expression

The **Event Key Expression** is a [CEL](https://cel.dev/) expression that you can use to create a dynamic event key from the payload and headers of the incoming webhook. You can either set this to a constant value, like `webhook`, or you could set it to something dynamic using those two options. Some examples:

1. `'stripe:' + input.type` would create event keys where `'stripe:'` is a prefix for all keys indicating the webhook came from Stripe, and `input.type` selects the `type` field off of the webhook payload and uses it to create the final event key. The result might look something like `stripe:payment_intent.created`.
2. `'github:' + headers['x-github-event'] + ':' + input.action` could create a key like `github:star:created`

<Callout type="info">
  The result of the event key expression is what Hatchet will use as the event
  key, so you'd need to set a matching event key as a trigger on your workflows
  in order to trigger them from the webhooks you create. For instance, you might
  add `on_events=["stripe:payment_intent.created"]` to listen for payment intent
  created events in the previous example.
</Callout>

#### Authentication

Finally, you'll need to specify how Hatchet should authenticate incoming webhook requests. For non-generic sources like Stripe and Github, Hatchet has presets for most of the fields, so in most cases you'd only need to provide a secret.

If you're using a generic source, then you'll need to specify an authentication method (either basic auth, an API key, HMAC-based auth), and provide the required fields (such as a username and password in the basic auth case).

<Callout type="warning">
  Hatchet encrypts any secrets you provide for validating incoming webhooks.
</Callout>

The different authentication methods require different fields to be provided:

- **Pre-configured sources** (Stripe, GitHub, Slack): Only require a webhook secret
- **Generic sources** require different fields depending on the selected authentication method:
  - **Basic Auth**: Requires a username and password
  - **API Key**: Requires header name containing the key on incoming requests, and secret key itself
  - **HMAC**: Requires a header name containing the secret on incoming requests, the secret itself, an encoding method (e.g. hex, base64), and an algorithm (e.g. `SHA256`, `SHA1`, etc.).

## Usage

While you're creating your webhook (and also after you've created it), you can copy the webhook URL, which is what you'll provide to the webhook _sender_.

Once you've done that, the last thing to do is register the event keys you want your workers to listen for so that they can be triggered by incoming webhooks.

For examples on how to do this, see the [documentation on event triggers](./run-on-event.mdx).
